package com.jzrh.flashbee.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzrh.flashbee.common.core.constant.UrlConstants;
import com.jzrh.flashbee.common.core.exception.ParamException;
import com.jzrh.flashbee.common.redis.utils.RedisCacheUtils;
import com.jzrh.flashbee.entity.FlashbeeUrl;
import com.jzrh.flashbee.entity.dto.UrlDTO;
import com.jzrh.flashbee.entity.vo.UrlVO;
import com.jzrh.flashbee.mapper.FlashbeeUrlMapper;
import com.jzrh.flashbee.service.IFlashbeeUrlService;
import com.jzrh.flashbee.common.utils.GenerateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author Jince
 * @since: 2023.11.22 下午 09:22
 * @description:
 */
@Service
@Slf4j
public class IFlashbeeUrlServiceImpl extends ServiceImpl<FlashbeeUrlMapper, FlashbeeUrl> implements IFlashbeeUrlService {
    @Resource
    private FlashbeeUrlMapper flashbeeUrlMapper;
    @Resource
    private RedisCacheUtils redisCacheUtils;

    /**
     * 生成短网址
     *
     * @param urlDTO  dto
     * @param request 请求头
     * @return vo
     */
    @Transactional
    @Override
    public UrlVO generateUrl(UrlDTO urlDTO, HttpServletRequest request) {
        try {
            URL url = new URL(urlDTO.getUrl());
            // 检查协议是否存在
            url.toURI();
        } catch (MalformedURLException | IllegalArgumentException | URISyntaxException e) {
            throw new ParamException("网址不正确");
        }
        String shortLink = "";
        while (true) {
            String link = GenerateUtil.generateShortLink();
            LambdaQueryWrapper<FlashbeeUrl> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(FlashbeeUrl::getUrlCoding, shortLink);
            if (!(this.count(lambdaQueryWrapper) > 0)) {
                shortLink = link;
                break;
            }
        }
        // 判断时间，如果没有指定时间则默认为7天
        if (Objects.isNull(urlDTO.getExpiration())) {
            urlDTO.setExpiration(7);
        }
        // 存储生成的短链接信息
        LocalDateTime localDateTime = LocalDateTime.now().plusDays(urlDTO.getExpiration());
        FlashbeeUrl flashbeeUrl = new FlashbeeUrl();
        flashbeeUrl.setOriginUrl(urlDTO.getUrl());
        flashbeeUrl.setExpiration(localDateTime);
        flashbeeUrl.setUrlCoding(shortLink);
        if (this.save(flashbeeUrl)) {
            redisCacheUtils.setObject(UrlConstants.SHORT_URL + shortLink, JSONObject.toJSONString(flashbeeUrl), (long) urlDTO.getExpiration(), TimeUnit.DAYS);
            String baseUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
            UrlVO urlVO = new UrlVO();
            urlVO.setOriginUrl(urlDTO.getUrl());
            urlVO.setUrl(baseUrl + "/" + shortLink);
            urlVO.setExpiration(localDateTime);
            return urlVO;
        }
        return null;
    }

    /**
     * 获取原始网址
     *
     * @return 原始网址
     */
    @Override
    public String getOriginUrl(String shortUrl) {
        FlashbeeUrl flashbeeUrl = JSONObject.parseObject(redisCacheUtils.getObject(UrlConstants.SHORT_URL + shortUrl), FlashbeeUrl.class);
        if(flashbeeUrl!=null){
            return flashbeeUrl.getOriginUrl();
        }else{
            LambdaQueryWrapper<FlashbeeUrl> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(FlashbeeUrl::getUrlCoding, shortUrl);
            FlashbeeUrl one = this.getOne(lambdaQueryWrapper);
            if (Objects.nonNull(one)) {
                return one.getOriginUrl();
            }
        }
        throw new ParamException("短网址以失效");
    }

    /**
     * 定时任务，定期删除过期短链
     */
    // @Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点执行
    @Scheduled(cron = "0 0 * * * *") // 每小时执行一次，整点触发
    public void cleanupData() {
        flashbeeUrlMapper.deleteExpirationUrl();
    }
}
